﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Data;
using System.Data.OracleClient;
using System.Configuration;
using AppModule.InterProcessComm;
using AppModule.NamedPipes;
using System.IO;
using System.Xml.Serialization;
using System.Xml;

namespace WCFHost.ResourceAccess
{
    public class Host
    {
        public List<String> Mensagens { get; set; }

        public string SerializeObject(Object pObject)
        {
            try
            {
                String XmlizedString = null;
                MemoryStream memoryStream = new MemoryStream();
                XmlSerializer xs = new XmlSerializer(pObject.GetType());
                XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
                xs.Serialize(xmlTextWriter, pObject);
                memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
                XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
                return XmlizedString;                
            }
            catch (Exception e)
            {
                System.Console.WriteLine(e);
                return null;
            }
        }

        private String UTF8ByteArrayToString(Byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            String constructedString = encoding.GetString(characters);
            return (constructedString);
        }

        private void EnviaMensagem(String mensagem)
        {
            IInterProcessConnection clientConnection = null;
            try
            {
                clientConnection = new ClientPipeConnection("PipeReceptor", ".");
                clientConnection.Connect();
                clientConnection.Write(mensagem);
                clientConnection.Close();
            }
            catch
            {
                clientConnection.Dispose();
            }
        }

        public List<DataContract.HostRequest> Message(Int64 codigoMembro, List<DataContract.HostRequest> obj)
        {
            DataContract.Monitor monitor = new WCFHost.DataContract.Monitor();
            
            using (OracleConnection cn = new OracleConnection(ConfigurationManager.AppSettings["ConnectionString"].ToString()))
            {
                try
                {                 
                    cn.Open();

                    // Atualiza o campo IN_OFMEGA da tabela TORPARM, caso seu valor seja diferente de 'H'
                    using (OracleCommand command = new OracleCommand("SELECT IN_OFMEGA FROM TORPARM", cn))
                    {
                        using (IDataReader reader = command.ExecuteReader())
                        {
                            if (reader.Read())
                            {
                                if (!reader.GetString(reader.GetOrdinal("IN_OFMEGA")).ToUpper().Equals("H"))
                                {
                                    using (OracleCommand commandUpd = new OracleCommand("UPDATE TORPARM SET IN_OFMEGA = 'H'", cn))
                                    {
                                        commandUpd.ExecuteNonQuery();
                                    }
                                }
                            }
                        }
                    }

                    String query = null;

                    foreach (DataContract.HostRequest hostRequest in obj)
                    {
                        try
                        {
                            String sinal = "";

                            if (hostRequest.Tabela == DataContract.Enum.Tabela.torsinl_ofer)
                            {
                                query = @"INSERT INTO TORSINL_OFER (DT_DATMOV, DT_SISTEMA, NR_SEQ, DS_SINAL)
                                                            VALUES (:DT_DATMOV, :DT_SISTEMA, :NR_SEQ, :DS_SINAL)";

                                using (OracleCommand command = new OracleCommand(query, cn))
                                {
                                    sinal = AlterarSinal(hostRequest.DescricaoSinal, Cliente(hostRequest.CodigoCliente, codigoMembro, true, cn), hostRequest.Tabela);

                                    command.Parameters.Add("DT_DATMOV", OracleType.DateTime).Value = hostRequest.DataMovimento;
                                    command.Parameters.Add("DT_SISTEMA", OracleType.DateTime).Value = hostRequest.DataSistema;
                                    command.Parameters.Add("NR_SEQ", OracleType.Int32).Value = hostRequest.NumeroSequencia;
                                    command.Parameters.Add("DS_SINAL", OracleType.VarChar).Value = sinal;

                                    command.ExecuteNonQuery();
                                }
                            }
                            else if (hostRequest.Tabela == DataContract.Enum.Tabela.torhub_txt)
                            {
                                query = @"INSERT INTO TORHUB_TXT (DT_DATMOV, CD_SISTEMA, NR_SEQ, DS_TXT, DT_TIMESTAMP)
                                                          VALUES (:DT_DATMOV, :CT_SISTEMA, :NR_SEQ, :DS_TXT, :DT_TIMESTAMP)";

                                using (OracleCommand command = new OracleCommand(query, cn))
                                {
                                    sinal = AlterarSinal(hostRequest.DescricaoSinal, Cliente(hostRequest.CodigoCliente, codigoMembro, false, cn), hostRequest.Tabela);

                                    command.Parameters.Add("DT_DATMOV", OracleType.DateTime).Value = hostRequest.DataMovimento;
                                    command.Parameters.Add("CT_SISTEMA", OracleType.VarChar).Value = hostRequest.CodigoSistema;
                                    command.Parameters.Add("NR_SEQ", OracleType.Int32).Value = hostRequest.NumeroSequencia;
                                    command.Parameters.Add("DS_TXT", OracleType.VarChar).Value = sinal;
                                    command.Parameters.Add("DT_TIMESTAMP", OracleType.DateTime).Value = hostRequest.DataTimeStamp;

                                    command.ExecuteNonQuery();
                                }
                            }

                            monitor.QtdeRegistro++;

                            hostRequest.Status = DataContract.Enum.Status.Processado;
                        }
                        catch(Exception ex)
                        {
                            monitor.Erro = new List<String>();
                            monitor.Erro.Add("ERRO:");
                            monitor.Erro.Add("");

                            if (hostRequest.Tabela == DataContract.Enum.Tabela.torsinl_ofer)
                            {
                                String sinal = AlterarSinal(hostRequest.DescricaoSinal, Cliente(hostRequest.CodigoCliente, codigoMembro, true, cn), hostRequest.Tabela);
                                monitor.Erro.Add(String.Format("DT_DATMOV: {0} - DT_SISTEMA: {1} - NR_SEQ: {2} - DT_TIMESTAMP: {3}", hostRequest.DataMovimento, hostRequest.DataSistema, hostRequest.NumeroSequencia, hostRequest.DataTimeStamp));
                                monitor.Erro.Add(String.Format("DS_SINAL: {0}", sinal));
                                monitor.Erro.Add("");
                            }
                            else if (hostRequest.Tabela == DataContract.Enum.Tabela.torhub_txt)
                            {
                                String sinal = AlterarSinal(hostRequest.DescricaoSinal, Cliente(hostRequest.CodigoCliente, codigoMembro, false, cn), hostRequest.Tabela);
                                monitor.Erro.Add(String.Format("DT_DATMOV: {0} - CT_SISTEMA: {1} - NR_SEQ: {2} - DT_TIMESTAMP: {3}", hostRequest.DataMovimento, hostRequest.CodigoSistema, hostRequest.NumeroSequencia, hostRequest.DataTimeStamp));
                                monitor.Erro.Add(String.Format("DS_TXT: {0}", sinal));
                                monitor.Erro.Add("");
                            }

                            monitor.Erro.Add(String.Format("-> Mensagem Erro: {0}", ex.Message));
                            monitor.Erro.Add("");

                            hostRequest.Status = DataContract.Enum.Status.Manutencao;
                            hostRequest.MensagemErro = ex.Message;

                            EnviaMensagem(SerializeObject(monitor));

                            return obj;
                        }
                    }

                    EnviaMensagem(SerializeObject(monitor));

                    try
                    {
                        PR_OFMEGA_OFERTA380_HUB(cn);

                        PR_NEGOCIOS_NEGAUT380_PROXY(Int64.Parse(ConfigurationManager.AppSettings["ID_ICAP"].ToString()), cn);

                        // Realiza a associação das ordens, suas execuções e os negócios realizados.
                        using (OracleCommand command = new OracleCommand("PR_CAAUTM.CASAMENTO_ESP", cn))
                        {
                            command.CommandType = CommandType.StoredProcedure;

                            command.Parameters.Add("P_DATMOV", OracleType.Char).Value = 'X';

                            command.ExecuteNonQuery();
                        }

                        using (OracleCommand command = new OracleCommand("PR_CALFME.FIN_MEG", cn))
                        {
                            command.CommandType = CommandType.StoredProcedure;

                            command.Parameters.Add("P_NADA", OracleType.Char).Value = 'X';

                            command.ExecuteNonQuery();
                        }
                    }
                    catch { }

                    //EnviaMensagem(SerializeObject(monitor));
                    
                    return obj;
                }                
                finally
                {
                    cn.Close();                 
                }                
            }
        }

        private String AlterarSinal(String descricaoSinal, String cliente, DataContract.Enum.Tabela tabela)
        {
            String oldValue = "";            

            if (tabela == WCFHost.DataContract.Enum.Tabela.torsinl_ofer)
            {
                cliente = cliente.PadLeft(8, '0');

                // 111,9
                if (descricaoSinal.Substring(16, 4).Equals("0103"))
                    oldValue = descricaoSinal.Substring(110, 8);
                // 136,9
                else if (descricaoSinal.Substring(16, 4).Equals("0105"))
                    oldValue = descricaoSinal.Substring(135, 8);
                // 102,9
                else if (descricaoSinal.Substring(16, 4).Equals("0138"))
                    oldValue = descricaoSinal.Substring(101, 8);
                // 189,9
                else if (descricaoSinal.Substring(16, 4).Equals("0172"))
                    oldValue = descricaoSinal.Substring(188, 8);
                // 138,9
                else if (descricaoSinal.Substring(16, 4).Equals("0411"))
                    oldValue = descricaoSinal.Substring(137, 8);
            }
            else if (tabela == WCFHost.DataContract.Enum.Tabela.torhub_txt)
            {
                cliente = cliente.PadLeft(7, '0');

                // 193,7
                oldValue = descricaoSinal.Substring(192, 7);
            }

            descricaoSinal = descricaoSinal.Replace(oldValue, cliente);
            
            return descricaoSinal;
        }

        /// <summary>
        /// Recupera o código do cliente
        /// </summary>        
        private String Cliente(Int64 codigoCliente, Int64 codigoMembro, Boolean carregarDigito, OracleConnection cn)
        {
            String query = @"SELECT CD_CLIENTE
                               FROM TSCCBOUTP A,
                                    TBOCORRESP B
                              WHERE A.CD_BOLSA = 'SP'
                                AND A.CD_CLIE_OUTR_BOLSA = :CD_CLIE_OUTR_BOLSA
                                AND A.IN_UTIL_CORRESP = 'S'                                                                            
                                AND B.CD_CORRESP = A.CD_MEMBRO
                                AND B.CD_MEMBRO_BOLSA = :CD_MEMBRO";

            using (OracleCommand command = new OracleCommand(query, cn))
            {
                command.Parameters.Add("CD_CLIE_OUTR_BOLSA", OracleType.Number).Value = codigoCliente;
                command.Parameters.Add("CD_MEMBRO", OracleType.Number).Value = codigoMembro;

                using (IDataReader reader = command.ExecuteReader())
                {
                    if (reader.Read())
                    {
                        // Carrega o dígito do cliente
                        if (carregarDigito)
                        {
                            query = @"SELECT DV_CLIENTE
                                        FROM TSCCLIBOL
                                       WHERE CD_CLIENTE = :CD_CLIENTE";

                            using (OracleCommand commandDv = new OracleCommand(query, cn))
                            {
                                commandDv.Parameters.Add("CD_CLIENTE", OracleType.Number).Value = reader.GetInt64(reader.GetOrdinal("CD_CLIENTE"));

                                using (IDataReader readerDv = commandDv.ExecuteReader())
                                {
                                    if (readerDv.Read())
                                        return reader["CD_CLIENTE"].ToString() + readerDv["DV_CLIENTE"].ToString();
                                    else
                                        return reader["CD_CLIENTE"].ToString();
                                }
                            }
                        }
                        else
                            return reader["CD_CLIENTE"].ToString();
                    }
                    else
                        return "";
                }
            }
        }

        /// <summary>
        /// Realiza a criação das ordens e montará as execuções.
        /// </summary>        
        private void PR_OFMEGA_OFERTA380_HUB(OracleConnection cn)
        {
            using (OracleCommand command = new OracleCommand("PR_OFMEGA.Oferta380_Hub", cn))
            {
                command.CommandType = CommandType.StoredProcedure;

                command.Parameters.Add("R_nCtrlRec", OracleType.Number).Direction = ParameterDirection.Output;
                command.Parameters.Add("R_nReproc", OracleType.Number).Direction = ParameterDirection.Output;
                
                command.ExecuteNonQuery();

                if (Int32.Parse(command.Parameters["R_nReproc"].Value.ToString()) != 0)
                    PR_OFMEGA_OFERTA380_HUB(cn);
            }
        }

        /// <summary>
        /// Realiza a inclusão dos negócios executados
        /// </summary>
        private void PR_NEGOCIOS_NEGAUT380_PROXY(Int64 codigoMembro, OracleConnection cn)
        {
            using (OracleCommand command = new OracleCommand("PR_NEGOCIOS.NEGAUT380_corresp", cn))
            {
                command.CommandType = CommandType.StoredProcedure;

                command.Parameters.Add("P_sCodCorr", OracleType.VarChar).Value = codigoMembro.ToString();
                command.Parameters.Add("R_nCtrlRec", OracleType.Number).Direction = ParameterDirection.Output;
                command.Parameters.Add("R_nReproc", OracleType.Number).Direction = ParameterDirection.Output;

                command.ExecuteNonQuery();

                if (Int32.Parse(command.Parameters["R_nReproc"].Value.ToString()) != 0)
                    PR_NEGOCIOS_NEGAUT380_PROXY(codigoMembro, cn);
            }
        }
    }
}
